home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / UTIL / Folder・Icon・Opener 1.0.1.sit / Folder•Icon•Opener 1.0.1 / source code / sources / FIOpen.open.c < prev    next >
Text File  |  1996-05-05  |  11KB  |  365 lines

  1. /*
  2.  *--------------------------------------------------------------
  3.  * FIOpen.open.c
  4.  *--------------------------------------------------------------
  5.  *    Most of source codes in this file come from StandardGetFolder
  6.  *    example written by Steve Falkenburg -- MacDTS, Apple Computer.
  7.  *    However, the author fully rewrite the codes in order to avoid
  8.  *    using global variables and make it PowerPC applicable.
  9.  *--------------------------------------------------------------
  10.  *    Written by Fumio Rokkaku, 1995-1996
  11.  *--------------------------------------------------------------
  12.  */
  13.  
  14. #pragma once
  15.  
  16. /* System Headers */
  17. #include <Memory.h>
  18. #include <Dialogs.h>
  19. #include <Controls.h>
  20. #include <Files.h>
  21. #include <Folders.h>
  22. #include <Finder.h>
  23. #include <Aliases.h>
  24. #include <Script.h>
  25. #include <StandardFile.h>
  26.  
  27. /* Project Headers */
  28. #include "FIOpen.h"
  29.  
  30. /* set __USE_DEBUGER to 1 when you use debugger on 68K Mac */
  31. #define    __USE_DEBUGER    0
  32. #define    __DEBUG_68K        (__USE_DEBUGER && !__powerpc)
  33.  
  34. /*
  35.  *--------------------------------------------------------------
  36.  *    constants
  37.  *--------------------------------------------------------------
  38.  */
  39. enum constGetFolderIDs {
  40.     kStdGetFolderID    = 1000,
  41.     kStrFolderID    = kStdGetFolderID
  42. };
  43. enum constGetFolderItems {
  44.     sfItemFolderButton    = 10
  45. };
  46. enum constGetFolderStrs {
  47.     iSelectIdx    = 1,
  48.     iDsktopIdx    = 2,
  49.     iFolderIdx    = 3
  50. };
  51.  
  52. /*
  53.  *--------------------------------------------------------------
  54.  *    type definition
  55.  *--------------------------------------------------------------
  56.  */
  57. typedef struct {
  58.     StandardFileReply    *sfReply;
  59.     FSSpec            prevSpec;
  60.     FSSpec            deskSpec;
  61.     Str15            dskTop;
  62.     Str15            select;
  63.     unsigned char    quoBgn;
  64.     unsigned char    quoEnd;
  65. } SFUserDataRec, *SFUserDataPtr;
  66.  
  67. /*
  68.  *--------------------------------------------------------------
  69.  *    prototypes
  70.  *--------------------------------------------------------------
  71.  */
  72. /* file filter procedures */
  73. pascal Boolean    MyCustomFileFilter(CInfoPBPtr, void *);
  74. pascal short    MyCustomSFHook(short, DialogRef, void *);
  75.  
  76. /* static functions only used in this source */
  77. static void SetUpMyHookData(SFUserDataPtr);
  78. static OSErr MakeCanonFSSpec(FSSpecPtr);
  79. static OSErr GetDesktopFolderSpec(const short, FSSpecPtr);
  80. static void SetSelectButtonName(DialogRef, StringPtr, SFUserDataPtr);
  81. static void DimTheButton(DialogRef, Boolean);
  82. static Boolean EqualFSSpec(const FSSpecPtr, const FSSpecPtr);
  83.  
  84. /*
  85.  *--------------------------------------------------------------
  86.  * StandardGetFolder
  87.  *--------------------------------------------------------------
  88.  *    it provides "Select file and folder" dialog 
  89.  *    note that this can be used only on System7 or greater
  90.  *--------------------------------------------------------------
  91.  */
  92. void CustomGetFolderOnly(StandardFileReply *theReply)
  93. {
  94.     Point                openPt;
  95.     SFTypeList            aList;
  96.     FileFilterYDUPP        MyFileFilterUPP = nil;
  97.     DlgHookYDUPP        MyDialogHookUPP = nil;
  98.     SFUserDataRec        sfUserData;
  99.  
  100.     /* initialize the reply flag */
  101.     theReply->sfGood = false;
  102.  
  103.     /* initialize dailog location with ridiculous values */
  104.     openPt.v = openPt.h = -1;
  105.  
  106.     /* initialize user data */
  107.     sfUserData.sfReply = theReply;
  108.     sfUserData.prevSpec.vRefNum = -9999;    /* init to ridiculous value */
  109.  
  110.     /* load constant strings */
  111.     GetIndString(sfUserData.select, kStrFolderID, iSelectIdx);
  112.     GetIndString(sfUserData.dskTop, kStrFolderID, iDsktopIdx);
  113.  
  114.     /* set quotation mark characters */
  115.     if (FontScript() != smRoman) {
  116.         sfUserData.quoBgn = '"';
  117.         sfUserData.quoEnd = '"';
  118.     } else {
  119.         sfUserData.quoBgn = 'メ';
  120.         sfUserData.quoEnd = 'モ';
  121.     }
  122.  
  123.     /* install hook and file filter UPPs */
  124.     MyFileFilterUPP = NewFileFilterYDProc(MyCustomFileFilter);
  125.     MyDialogHookUPP    = NewDlgHookYDProc(MyCustomSFHook);
  126.  
  127.     /* if the UPPs are valid, then... */
  128.     if ((MyFileFilterUPP != nil) && (MyDialogHookUPP != nil)) {
  129.  
  130.         /* open get folder dialog */
  131.         CustomGetFile(MyFileFilterUPP, -1, aList, theReply, kStdGetFolderID,
  132.             openPt, MyDialogHookUPP, nil, nil, nil, &sfUserData);
  133.  
  134.         /* clean up the UPPs */
  135.         DisposeRoutineDescriptor(MyFileFilterUPP);
  136.         DisposeRoutineDescriptor(MyDialogHookUPP);
  137.     }
  138. }
  139. /*
  140.  *--------------------------------------------------------------
  141.  * MyCustomFileFilter
  142.  *--------------------------------------------------------------
  143.  *    this filter passes only visible folders
  144.  *--------------------------------------------------------------
  145.  */
  146. pascal Boolean MyCustomFileFilter(CInfoPBPtr thePB, void *userData)
  147. {
  148. #pragma unused(userData)
  149.  
  150.     unsigned short    fileFlags = thePB->hFileInfo.ioFlFndrInfo.fdFlags;
  151.     char            fileAttrb = thePB->hFileInfo.ioFlAttrib;
  152.  
  153.     return (
  154.         ((fileAttrb & ioDirMask) == 0)
  155.      ||    ((fileFlags & kIsInvisible) != 0)
  156.     );
  157. }
  158. /*
  159.  *--------------------------------------------------------------
  160.  * MyCustomSFHook
  161.  *--------------------------------------------------------------
  162.  *    this dialog hook checks the contents of the additional edit
  163.  *    fields when the user selects a file.  The focus of the dialog
  164.  *    is changed if one of the fields is out of range.
  165.  *--------------------------------------------------------------
  166.  */
  167. pascal short MyCustomSFHook(short theItem, DialogRef theDialog, void *userData)
  168. {
  169. #if    __DEBUG_68K
  170.     /* this is not needed at runtime but just for debugging on 68K Mac */
  171.     long    oldA5 = SetA5(SetCurrentA5());
  172. #endif
  173.  
  174.     SFUserDataPtr        sfUserData;
  175.     StandardFileReply    *sfUserRepl;
  176.     FSSpecPtr            sfReplSpec, sfPrevSpec;
  177.  
  178.     if (GetWRefCon(GetDialogWindow(theDialog)) != sfMainDialogRefCon) {
  179.         return (theItem);
  180.     }
  181.  
  182.     /* copy SFUserData structure's pointers and contents */
  183.     sfUserData = (SFUserDataPtr)userData;
  184.     sfUserRepl = sfUserData->sfReply;
  185.     sfPrevSpec = &sfUserData->prevSpec;
  186.     sfReplSpec = &sfUserRepl->sfFile;
  187.  
  188.     /* check dialog button operations */
  189.     switch (theItem) {
  190.  
  191.      case sfHookFirstCall:
  192.  
  193. /*    ====
  194.     This is a sample to locate a default folder when the dialog is firstly openeFIOpen...
  195.     This sample opens the system folder at always the dialog is opneFIOpen.
  196.     You can give a folder you want to specify in the sfUserRepl->sfIsFolder before
  197.     calling StandardGetFolder.
  198.     ==== */
  199. /*    ====
  200.         if (FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
  201.                     &sfReplSpec->vRefNum, &sfReplSpec->parID) == noErr) {
  202.             theItem = sfHookChangeSelection;
  203.         }
  204.     ==== */
  205.         break;
  206.  
  207.      case sfItemVolumeUser:
  208.         /* if volume is changed, */
  209.         sfReplSpec->name[0]    = 0;
  210.         sfReplSpec->parID    = fsRtDirID;
  211.         sfUserRepl->sfIsFolder = false;
  212.         sfUserRepl->sfIsVolume = false;
  213.         sfUserRepl->sfFlags = 0;
  214.         theItem = sfHookChangeSelection;
  215.         break;
  216.  
  217.      case sfItemFolderButton:
  218.          /* when the folder select button is pressed, make it to be selected */
  219.         theItem = sfItemOpenButton;
  220.         break;
  221.  
  222.      case sfHookNullEvent:
  223.         /* check currently selected file or folder item */
  224.         if (EqualFSSpec(sfReplSpec, sfPrevSpec) == false) {
  225.     
  226.             FSSpec    currSpec;
  227.     
  228.             currSpec = *sfReplSpec;
  229.             MakeCanonFSSpec(&currSpec);
  230.     
  231.             /* get a desktop folder of the newly selected volume */
  232.             if (currSpec.vRefNum != sfPrevSpec->vRefNum) {
  233.                 GetDesktopFolderSpec(currSpec.vRefNum, &sfUserData->deskSpec);
  234.             }
  235.     
  236.             /* if the current folder is the desktop, dim the select button */
  237.             DimTheButton(theDialog, EqualFSSpec(&sfUserData->deskSpec, &currSpec));
  238.     
  239.             /* show the currently selected file or folder in the button */
  240.             SetSelectButtonName(theDialog, currSpec.name, sfUserData);
  241.             *sfPrevSpec = *sfReplSpec;
  242.         }
  243.         break;
  244.  
  245.      case sfHookLastCall:
  246.          /* if none is selected, return the parent folder */
  247.         if (Length(sfReplSpec->name) == 0) {
  248.             MakeCanonFSSpec(sfReplSpec);
  249.         }
  250.         break;
  251.     }
  252.  
  253. #if    __DEBUG_68K
  254.     (void)SetA5(oldA5);
  255. #endif
  256.     return (theItem);
  257. }
  258. /*
  259.  *--------------------------------------------------------------
  260.  * MakeCanonFSSpec
  261.  *--------------------------------------------------------------
  262.  *    when the given FSSpec name is empty,
  263.  *    make its parent directory spec
  264.  *--------------------------------------------------------------
  265.  */
  266. static OSErr MakeCanonFSSpec(FSSpecPtr theSpec)
  267. {
  268.     OSErr result = noErr;
  269.  
  270.     if (Length(theSpec->name) == 0) {
  271.         result = FSMakeFSSpec(theSpec->vRefNum, theSpec->parID, nil, theSpec);
  272.     }
  273.     return (result);
  274. }
  275. /*
  276.  *--------------------------------------------------------------
  277.  * GetDesktopFolderSpec
  278.  *--------------------------------------------------------------
  279.  *    get an FSSpec that indicates the volume's desktop
  280.  *--------------------------------------------------------------
  281.  */
  282. static OSErr GetDesktopFolderSpec(
  283.     const short    theVRefNum,
  284.     FSSpecPtr    theFolderSpec)
  285. {
  286.     OSErr result;
  287.     
  288.     theFolderSpec->name[0] = 0;
  289.     result = FindFolder(theVRefNum, kDesktopFolderType, kDontCreateFolder,
  290.                 &theFolderSpec->vRefNum, &theFolderSpec->parID);
  291.  
  292.     if (result == noErr) {
  293.         result = MakeCanonFSSpec(theFolderSpec);
  294.     }
  295.     return (result);
  296. }
  297. /*
  298.  *--------------------------------------------------------------
  299.  * SetSelectButtonName
  300.  *--------------------------------------------------------------
  301.  *    set name of the folder/file select button
  302.  *--------------------------------------------------------------
  303.  */
  304. static void SetSelectButtonName(
  305.     DialogRef        theDialog,
  306.     StringPtr        selectedName,
  307.     SFUserDataPtr    showStrs)
  308. {
  309.     Handle    folderBttn;
  310.     Str255    bttnTitle;
  311.     Str63    tempSelectName;
  312.     Rect    iRect;
  313.     short    iType;
  314.  
  315.     /* get folder select button */
  316.     GetDialogItem(theDialog, sfItemFolderButton, &iType, &folderBttn, &iRect);
  317.  
  318.     {    /* truncate file or folder name if it is wider than the button */
  319.         short bttnWidth =
  320.                 (iRect.right - iRect.left) - 4
  321.                 - StringWidth(showStrs->select)
  322.                 - (CharWidth(showStrs->quoBgn) * 2);
  323.         PStrCpy(selectedName, tempSelectName);
  324.         TruncString(bttnWidth, tempSelectName, smTruncMiddle);
  325.     }
  326.  
  327.     /* make a new button title */
  328.     PStrCpy(showStrs->select, bttnTitle);        /* "Select " */
  329.     CatChar(showStrs->quoBgn, bttnTitle);        /* "メ" or """ */
  330.     PStrCat(tempSelectName, bttnTitle);            /* "(file or folder name)" */
  331.     CatChar(showStrs->quoEnd, bttnTitle);        /* "モ" or """ */
  332.  
  333.     /* set new button title */
  334.     SetControlTitle((ControlRef)folderBttn, bttnTitle);
  335. }
  336. /*
  337.  *--------------------------------------------------------------
  338.  * DimTheButton
  339.  *--------------------------------------------------------------
  340.  *    deactivate/activate the "folder select" button
  341.  *--------------------------------------------------------------
  342.  */
  343. static void DimTheButton(DialogRef theDialog, Boolean makeItDim)
  344. {
  345.     Handle    aButton;    Rect    aRect;    short    aType;
  346.  
  347.     GetDialogItem(theDialog, sfItemFolderButton, &aType, &aButton, &aRect);
  348.     HiliteControl((ControlRef)aButton, (makeItDim) ? kControlInactivePart : kControlNoPart);
  349. }
  350. /*
  351.  *--------------------------------------------------------------
  352.  * EqualFSSpec
  353.  *--------------------------------------------------------------
  354.  *    compare two FSSpec contents, turn true if they are the same
  355.  *--------------------------------------------------------------
  356.  */
  357. static Boolean EqualFSSpec(const FSSpecPtr specA, const FSSpecPtr specB)
  358. {
  359.     return (
  360.         specA->vRefNum == specB->vRefNum
  361.      && specA->parID   == specB->parID
  362.      && EqualString(specA->name, specB->name, false, true)
  363.     );
  364. }
  365.